<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Resumable C++ 20 Coroutines</title>
<link rel="stylesheet" href="../../../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="../../../boost_asio.html" title="Boost.Asio">
<link rel="up" href="../core.html" title="Core Concepts and Functionality">
<link rel="prev" href="cpp20_coroutines.html" title="C++20 Coroutines Support">
<link rel="next" href="../networking.html" title="Networking">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td>
<td align="center"><a href="../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="cpp20_coroutines.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../core.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../../boost_asio.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="../networking.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h4 class="title">
<a name="boost_asio.overview.core.coro"></a><a class="link" href="coro.html" title="Resumable C++ 20 Coroutines">Resumable C++ 20 Coroutines</a>
</h4></div></div></div>
<div class="note"><table border="0" summary="Note">
<tr>
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../doc/src/images/note.png"></td>
<th align="left">Note</th>
</tr>
<tr><td align="left" valign="top"><p>
            This is an experimental feature.
          </p></td></tr>
</table></div>
<p>
          The <a class="link" href="../../reference/experimental__coro.html" title="experimental::coro"><code class="computeroutput">experimental::coro</code></a>
          class provides support for a universal C++20 coroutine. These coroutines
          can be used as tasks, generators and transfomers, depending on their signature.
        </p>
<pre class="programlisting">coro&lt;std::string_view&gt; line_reader(tcp::socket stream)
{
   while (stream.is_open())
   {
     std::array&lt;char, 4096&gt; buf;

     auto read = co_await stream.async_read_some(
         boost::asio::buffer(buf), experimental::use_coro);

     if (read == 0u)
       continue;

     co_yield std::string_view { buf.data(), read };
   }
}

coro&lt;void, std::size_t&gt; line_logger(tcp::socket stream)
{
  std::size_t lines_read = 0u;
  auto reader = line_reader(std::move(stream));
  while (auto l = co_await reader)
  {
    std::cout &lt;&lt; "Read: '" &lt;&lt; *l &lt;&lt; "'" &lt;&lt; std::endl;
    lines_read++;
  }
  co_return lines_read;
}

void read_lines(tcp::socket sock)
{
  co_spawn(line_logger(std::move(sock),
      [](std::exception_ptr, std::size_t lines)
      {
        std::clog &lt;&lt; "Read " &lt;&lt; lines &lt;&lt; " lines" &lt;&lt; std::endl;
      }));
}
</pre>
<p>
          A <a class="link" href="../../reference/experimental__coro.html" title="experimental::coro"><code class="computeroutput">coro</code></a>
          is highly configurable, so that it can cover a set of different use cases.
        </p>
<pre class="programlisting">template&lt;
    typename Yield,
    typename Return = void,
    typename Executor = any_io_executor&gt;
struct coro;
</pre>
<h6>
<a name="boost_asio.overview.core.coro.h0"></a>
          <span class="phrase"><a name="boost_asio.overview.core.coro.yield"></a></span><a class="link" href="coro.html#boost_asio.overview.core.coro.yield">Yield</a>
        </h6>
<p>
          The <code class="computeroutput">Yield</code> parameter designates how a <code class="computeroutput">co_yield</code>
          statement behaves. It can either be a type, like <code class="computeroutput">int</code> or a
          signature with zero or one types:
        </p>
<pre class="programlisting">coro&lt;void&gt; // A coroutine with no yield
coro&lt;int&gt; // A coroutine that can yield int

coro&lt;void()&gt; // A coroutine with no yield
coro&lt;int()&gt; // A coroutine that can yield int

coro&lt;int(double)&gt; // A coroutine that can yield int and receive double
</pre>
<p>
          Receiving a value means that the <code class="computeroutput">co_yield</code> statement returns
          a value.
        </p>
<pre class="programlisting">coro&lt;int(int)&gt; my_sum(any_io_executor)
{
  int value = 0;
  while (true)
    value += co_yield value; //sum up all values
}
</pre>
<p>
          Putting values into a coroutine can be done it two ways: either by direct
          resumption (from another coro) or through async_resume. The first value
          gets ignored because the coroutines are lazy.
        </p>
<pre class="programlisting">coro&lt;void&gt; c(any_io_executor exec)
{
  auto sum = my_sum(exec);
  assert(0  == co_await sum(-1));
  assert(0  == co_await sum(10));
  assert(10 == co_await sum(15));
  assert(25 == co_await sum(0));
}

awaitable&lt;void&gt; a()
{
  auto sum = my_sum(co_await this_coro::executor);
  assert(0  == co_await sum.async_resume(-1, use_awaitable));
  assert(0  == co_await sum.async_resume(10, use_awaitable));
  assert(10 == co_await sum.async_resume(15, use_awaitable));
  assert(25 == co_await sum.async_resume(0, use_awaitable));
}
</pre>
<h6>
<a name="boost_asio.overview.core.coro.h1"></a>
          <span class="phrase"><a name="boost_asio.overview.core.coro._code_noexcept__code_"></a></span><a class="link" href="coro.html#boost_asio.overview.core.coro._code_noexcept__code_"><code class="computeroutput">noexcept</code></a>
        </h6>
<p>
          A coro may be noexcept:
        </p>
<pre class="programlisting">coro&lt;void() noexcept&gt; c;
coro&lt;int() noexcept&gt; c;
coro&lt;int(double) noexcept&gt; c;
</pre>
<p>
          This will change its @c async_resume signature, from <code class="computeroutput">void(std::exception_ptr)</code>
          to <code class="computeroutput">void()</code> or <code class="computeroutput">void(std::exception_ptr, T)</code> to
          <code class="computeroutput">void(T)</code>. A noexcept coro that ends with an exception will
          cause <code class="computeroutput">std::terminate</code> to be called.
        </p>
<p>
          Furthermore, calls of <code class="computeroutput">async_resume</code> and <code class="computeroutput">co_await</code>
          of an expired noexcept coro will cause undefined behaviour.
        </p>
<h6>
<a name="boost_asio.overview.core.coro.h2"></a>
          <span class="phrase"><a name="boost_asio.overview.core.coro.return"></a></span><a class="link" href="coro.html#boost_asio.overview.core.coro.return">Return</a>
        </h6>
<p>
          A coro can also define a type that can be used with <code class="computeroutput">co_return</code>:
        </p>
<pre class="programlisting">coro&lt;void() noexcept, int&gt; c(any_io_executor)
{
  co_return 42;
}
</pre>
<p>
          A coro can have both a <code class="computeroutput">Yield</code> and <code class="computeroutput">Return</code> that
          are non void at the same time.
        </p>
<h6>
<a name="boost_asio.overview.core.coro.h3"></a>
          <span class="phrase"><a name="boost_asio.overview.core.coro.result"></a></span><a class="link" href="coro.html#boost_asio.overview.core.coro.result">Result</a>
        </h6>
<p>
          The result type of a coroutine is dermined by both <code class="computeroutput">Yield</code> and
          <code class="computeroutput">Return</code>. Note that in the follwing table only the yield output
          value is considered, i.e. <code class="computeroutput">T(U)</code> means <code class="computeroutput">T</code>.
        </p>
<div class="table">
<a name="boost_asio.overview.core.coro.t0"></a><p class="title"><b>Table 2. :result_type Result type deduction</b></p>
<div class="table-contents"><table class="table" summary=":result_type Result type deduction">
<colgroup>
<col>
<col>
<col>
<col>
<col>
</colgroup>
<thead><tr>
<th>
                  <p>
                    Yield
                  </p>
                </th>
<th>
                  <p>
                    Return
                  </p>
                </th>
<th>
                  <p>
                    <code class="computeroutput">noexcept</code>
                  </p>
                </th>
<th>
                  <p>
                    <code class="computeroutput">result_type</code>
                  </p>
                </th>
<th>
                  <p>
                    <code class="computeroutput">completion_signature</code>
                  </p>
                </th>
</tr></thead>
<tbody>
<tr>
<td>
                  <p>
                    <code class="computeroutput">T</code>
                  </p>
                </td>
<td>
                  <p>
                    <code class="computeroutput">U</code>
                  </p>
                </td>
<td>
                  <p>
                    <code class="computeroutput">false</code>
                  </p>
                </td>
<td>
                  <p>
                    <code class="computeroutput">variant&lt;T, U&gt;</code>
                  </p>
                </td>
<td>
                  <p>
                    <code class="computeroutput">void(std::exception_ptr, variant&lt;T, U&gt;)</code>
                  </p>
                </td>
</tr>
<tr>
<td>
                  <p>
                    <code class="computeroutput">T</code>
                  </p>
                </td>
<td>
                  <p>
                    <code class="computeroutput">U</code>
                  </p>
                </td>
<td>
                  <p>
                    <code class="computeroutput">true</code>
                  </p>
                </td>
<td>
                  <p>
                    <code class="computeroutput">variant&lt;T, U&gt;</code>
                  </p>
                </td>
<td>
                  <p>
                    <code class="computeroutput">void(variant&lt;T, U&gt;)</code>
                  </p>
                </td>
</tr>
<tr>
<td>
                  <p>
                    <code class="computeroutput">T</code>
                  </p>
                </td>
<td>
                  <p>
                    <code class="computeroutput">void</code>
                  </p>
                </td>
<td>
                  <p>
                    <code class="computeroutput">false</code>
                  </p>
                </td>
<td>
                  <p>
                    <code class="computeroutput">optional&lt;T&gt;</code>
                  </p>
                </td>
<td>
                  <p>
                    <code class="computeroutput">void(std::exception_ptr, optional&lt;T&gt;)</code>
                  </p>
                </td>
</tr>
<tr>
<td>
                  <p>
                    <code class="computeroutput">T</code>
                  </p>
                </td>
<td>
                  <p>
                    <code class="computeroutput">void</code>
                  </p>
                </td>
<td>
                  <p>
                    <code class="computeroutput">true</code>
                  </p>
                </td>
<td>
                  <p>
                    <code class="computeroutput">optional&lt;T&gt;</code>
                  </p>
                </td>
<td>
                  <p>
                    <code class="computeroutput">void(optional&lt;T&gt;)</code>
                  </p>
                </td>
</tr>
<tr>
<td>
                  <p>
                    <code class="computeroutput">void</code>
                  </p>
                </td>
<td>
                  <p>
                    <code class="computeroutput">void</code>
                  </p>
                </td>
<td>
                  <p>
                    <code class="computeroutput">false</code>
                  </p>
                </td>
<td>
                  <p>
                    <code class="computeroutput">optional&lt;T&gt;</code>
                  </p>
                </td>
<td>
                  <p>
                    <code class="computeroutput">void(std::exception_ptr)</code>
                  </p>
                </td>
</tr>
<tr>
<td>
                  <p>
                    <code class="computeroutput">void</code>
                  </p>
                </td>
<td>
                  <p>
                    <code class="computeroutput">void</code>
                  </p>
                </td>
<td>
                  <p>
                    <code class="computeroutput">true</code>
                  </p>
                </td>
<td>
                  <p>
                    <code class="computeroutput">optional&lt;T&gt;</code>
                  </p>
                </td>
<td>
                  <p>
                    <code class="computeroutput">void()</code>
                  </p>
                </td>
</tr>
<tr>
<td>
                  <p>
                    <code class="computeroutput">void</code>
                  </p>
                </td>
<td>
                  <p>
                    <code class="computeroutput">T</code>
                  </p>
                </td>
<td>
                  <p>
                    <code class="computeroutput">false</code>
                  </p>
                </td>
<td>
                  <p>
                    <code class="computeroutput">optional&lt;T&gt;</code>
                  </p>
                </td>
<td>
                  <p>
                    <code class="computeroutput">void(std::exception_ptr, T)</code>
                  </p>
                </td>
</tr>
<tr>
<td>
                  <p>
                    <code class="computeroutput">void</code>
                  </p>
                </td>
<td>
                  <p>
                    <code class="computeroutput">T</code>
                  </p>
                </td>
<td>
                  <p>
                    <code class="computeroutput">true</code>
                  </p>
                </td>
<td>
                  <p>
                    <code class="computeroutput">optional&lt;T&gt;</code>
                  </p>
                </td>
<td>
                  <p>
                    <code class="computeroutput">void(T)</code>
                  </p>
                </td>
</tr>
</tbody>
</table></div>
</div>
<br class="table-break"><h6>
<a name="boost_asio.overview.core.coro.h4"></a>
          <span class="phrase"><a name="boost_asio.overview.core.coro.executor"></a></span><a class="link" href="coro.html#boost_asio.overview.core.coro.executor">Executor</a>
        </h6>
<p>
          Every coroutine needs to have its own executor. Since the coroutine gets
          called multiple times, it cannot take the executor from the caller like
          an <code class="computeroutput">awaitable</code>. Therefore a <code class="computeroutput">coro</code> requires to get
          an executor or an execution_context passed in as the first parameter.
        </p>
<pre class="programlisting">coro&lt;int&gt; with_executor(any_io_executor);
coro&lt;int&gt; with_context(io_context &amp;);
</pre>
<p>
          It is to note, that an execution_context is defined as loosely as possible.
          An execution context is any object that has a <code class="computeroutput">get_executor()</code>
          function, which returns an executor that can be transformed into the executor_type
          of the coroutine. This allows most io_objects to be used as the source
          of the executor:
        </p>
<pre class="programlisting">coro&lt;int&gt; with_socket(tcp::socket);
</pre>
<p>
          Additionally, a <code class="computeroutput">coro</code> that is a member function will check
          the <code class="computeroutput">this</code> pointer as well, either if it's an executor or an
          execution context:
        </p>
<pre class="programlisting">struct my_io_object
{
  any_io_executor get_executor();

  coro&lt;int&gt; my_coro();
};
</pre>
<p>
          Finally, a member coro can be given an explicit executor or execution context,
          to override the one of the object:
        </p>
<pre class="programlisting">struct my_io_object
{
  any_io_executor get_executor();

  coro&lt;int&gt; my_coro(any_io_executor exec); // it will use exec
};
</pre>
<h6>
<a name="boost_asio.overview.core.coro.h5"></a>
          <span class="phrase"><a name="boost_asio.overview.core.coro._code_co_await__code_"></a></span><a class="link" href="coro.html#boost_asio.overview.core.coro._code_co_await__code_"><code class="computeroutput">co_await</code></a>
        </h6>
<p>
          The @c co_await within a <code class="computeroutput">coro</code> is not the same as <code class="computeroutput">async_resume(use_coro)</code>,
          unless both coros use different executors. If they use the same, the <code class="computeroutput">coro</code>
          will direclty suspend and resume the executor, without any usage of the
          executor.
        </p>
<p>
          <code class="computeroutput">co_await this_coro::</code> behaves the same as coroutines that use
          @c boost::asio::awaitable.
        </p>
<h6>
<a name="boost_asio.overview.core.coro.h6"></a>
          <span class="phrase"><a name="boost_asio.overview.core.coro.integrating_with_awaitable"></a></span><a class="link" href="coro.html#boost_asio.overview.core.coro.integrating_with_awaitable">Integrating
          with awaitable</a>
        </h6>
<p>
          As the <code class="computeroutput">coro</code> member function <code class="computeroutput">async_resume</code> is an
          asynchronous operation, it may also be used in conjunction with <code class="computeroutput">awaitable</code>
          coroutines in a single control flow. For example:
        </p>
<pre class="programlisting">#include &lt;asio.hpp&gt;
#include &lt;boost/asio/experimental/coro.hpp&gt;

using boost::asio::ip::tcp;

boost::asio::experimental::coro&lt;std::string&gt; reader(tcp::socket&amp; sock)
{
  std::string buf;
  while (sock.is_open())
  {
    std::size_t n = co_await boost::asio::async_read_until(
        sock, boost::asio::dynamic_buffer(buf), '\n',
        boost::asio::experimental::use_coro);
    co_yield buf.substr(0, n);
    buf.erase(0, n);
  }
}

boost::asio::awaitable&lt;void&gt; consumer(tcp::socket sock)
{
  auto r = reader(sock);
  auto msg1 = co_await r.async_resume(boost::asio::use_awaitable);
  std::cout &lt;&lt; "Message 1: " &lt;&lt; msg1.value_or("\n");
  auto msg2 = co_await r.async_resume(boost::asio::use_awaitable);
  std::cout &lt;&lt; "Message 2: " &lt;&lt; msg2.value_or("\n");
}

boost::asio::awaitable&lt;void&gt; listen(tcp::acceptor&amp; acceptor)
{
  for (;;)
  {
    co_spawn(
        acceptor.get_executor(),
        consumer(co_await acceptor.async_accept(boost::asio::use_awaitable)),
        boost::asio::detached);
  }
}

int main()
{
  boost::asio::io_context ctx;
  tcp::acceptor acceptor(ctx, {tcp::v4(), 54321});
  co_spawn(ctx, listen(acceptor), boost::asio::detached);
  ctx.run();
}
</pre>
<h6>
<a name="boost_asio.overview.core.coro.h7"></a>
          <span class="phrase"><a name="boost_asio.overview.core.coro.see_also"></a></span><a class="link" href="coro.html#boost_asio.overview.core.coro.see_also">See
          Also</a>
        </h6>
<p>
          <a class="link" href="../../reference/co_spawn.html" title="co_spawn">co_spawn</a>, <a class="link" href="../../reference/experimental__coro.html" title="experimental::coro">experimental::coro</a>,
          <a class="link" href="cpp20_coroutines.html" title="C++20 Coroutines Support">C++20 Coroutines</a>,
          <a class="link" href="spawn.html" title="Stackful Coroutines">Stackful Coroutines</a>,
          <a class="link" href="coroutine.html" title="Stackless Coroutines">Stackless Coroutines</a>.
        </p>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright © 2003-2021 Christopher
      M. Kohlhoff<p>
        Distributed under the Boost Software License, Version 1.0. (See accompanying
        file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
      </p>
</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="cpp20_coroutines.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../core.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../../boost_asio.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="../networking.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>
